{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "nbsphinx": "hidden"
   },
   "source": [
    "This notebook is part of the `clifford` documentation: https://clifford.readthedocs.io/."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Conformal Geometric Algebra"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Conformal Geometric Algebra (CGA) is a projective geometry tool which allows conformal transformations to be implemented with rotations.   To do this,  the original geometric algebra is extended by two dimensions, one of positive signature $e_+$ and one of negative signature $e_-$. Thus, if we started with $G_p$,  the conformal algebra is  $G_{p+1,1}$.\n",
    "\n",
    "It is convenient to define a *null* basis given by \n",
    "\n",
    "$$e_{o} = \\frac{1}{2}(e_{-} -e_{+})\\\\e_{\\infty} = e_{-}+e_{+}$$\n",
    "\n",
    "A vector in the original space $x$ is *up-projected* into a conformal vector $X$  by \n",
    "\n",
    "$$X = x + \\frac{1}{2} x^2 e_{\\infty} +e_o $$\n",
    "\n",
    "\n",
    "To map a conformal vector back into a vector from the original space, the vector is first normalized, then rejected from the minkowski plane $E_0$,\n",
    "\n",
    "\n",
    "$$ X = \\frac{X}{X \\cdot e_{\\infty}}$$\n",
    "\n",
    "then \n",
    "\n",
    "$$x = X \\wedge E_0\\, E_0^{-1}$$\n",
    "\n",
    "\n",
    "To implement this in `clifford`  we could create a CGA by instantiating the it directly, like `Cl(3,1)`  for example, and then making the definitions and maps described above relating the various subspaces. Or, we you can use the helper function `conformalize()`. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using `conformalize()`\n",
    "The purpose of `conformalize()` is to remove the redundancy associated with creating a conformal geometric algebras. `conformalize()` takes an existing geometric algebra layout and *conformalizes* it by adding two dimensions, as described above. Additionally, this function returns a new layout for the CGA, a dict of blades for the CGA, and dictionary containing the added basis vectors and up/down projection functions. \n",
    "\n",
    "To demonstrate we will conformalize $G_2$, producing a CGA of $G_{3,1}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from numpy import pi,e\n",
    "from clifford import Cl, conformalize\n",
    "\n",
    "G2, blades_g2 = Cl(2)\n",
    "\n",
    "blades_g2 # inspect the G2 blades"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, conformalize it "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "G2c, blades_g2c, stuff = conformalize(G2)\n",
    "\n",
    "blades_g2c   #inspect the CGA blades"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Additionally lets inspect `stuff` "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "stuff"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It contains the following:\n",
    "\n",
    "* `ep` - positive basis vector added\n",
    "* `en` - negative basis vector added\n",
    "* `eo` - zero vector of null basis (=.5*(en-ep))\n",
    "* `einf` - infinity vector of null basis (=en+ep)\n",
    "* `E0` - minkowski bivector (=einf^eo)\n",
    "* `up()` - function to up-project a vector from GA to CGA\n",
    "* `down()` - function to down-project a vector from CGA to GA\n",
    "* `homo()` - function to homogenize a CGA vector\n",
    "\n",
    "\n",
    "We can put the `blades` and the `stuff` into the local namespace, "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "locals().update(blades_g2c)\n",
    "locals().update(stuff)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can use the `up()` and `down()` functions to go in and out of CGA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = e1+e2\n",
    "X = up(x)\n",
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "down(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Operations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Conformal transformations in $G_n$ are achieved through versors in the conformal space $G_{n+1,1}$. These versors can be categorized by their relation to the added minkowski plane, $E_0$. There are three categories,\n",
    "\n",
    "* versor purely in $E_0$\n",
    "* versor partly in $E_0$\n",
    "* versor out of $E_0$\n",
    "\n",
    "\n",
    "A three dimensional projection for conformal space with the relevant subspaces labeled is shown below.\n",
    "\n",
    "![axes showing e1 and the E0 plane](../../_static/conformal_space.svg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Versors purely in $E_0$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First we generate some vectors in G2, which we can operate on"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a= 1*e1 + 2*e2\n",
    "b= 3*e1 + 4*e2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Inversions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$e_{+} X e_{+}$$\n",
    "\n",
    "Inversion is a reflection in  $e_+$, this swaps $e_o$  and $e_{\\infty}$, as can be seen from the model above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert(down(ep*up(a)*ep)  == a.inv())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Involutions "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$E_0 X E_0$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert(down(E0*up(a)*E0) == -a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Dilations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$D_{\\alpha}  =  e^{-\\frac{\\ln{\\alpha}}{2} \\,E_0} $$\n",
    "\n",
    "$$D_{\\alpha} \\, X \\, \\tilde{D_{\\alpha}} $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy import rand,log\n",
    "\n",
    "D = lambda alpha: e**((-log(alpha)/2.)*(E0)) \n",
    "alpha = rand()\n",
    "assert(down( D(alpha)*up(a)*~D(alpha)) == (alpha*a))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Versors partly in $E_0$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Translations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$ V = e ^{\\frac{1}{2} e_{\\infty} a } = 1 + e_{\\infty}a$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "T = lambda x: e**(1/2.*(einf*x)) \n",
    "assert(down( T(a)*up(b)*~T(a)) == b+a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Transversions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A transversion is an inversion,  followed by a translation, followed by a inversion. The versor is \n",
    "\n",
    "$$V= e_+ T_a e_+$$\n",
    "\n",
    "which is recognised as the translation bivector reflected in the $e_+$ vector. From the diagram, it is seen that this is equivalent to the bivector in $x\\wedge e_o$,\n",
    "\n",
    "$$ e_+ (1+e_{\\infty}a)e_+ $$\n",
    "\n",
    "$$ e_+^2 + e_+e_{\\infty}a e_+$$\n",
    "$$2 +2e_o a$$\n",
    "\n",
    "the factor of 2 may be dropped, because the conformal vectors are null\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "V = ep * T(a) * ep\n",
    "assert ( V == 1+(eo*a))\n",
    "\n",
    "K = lambda x: 1+(eo*a) \n",
    "\n",
    "B= up(b)\n",
    "assert( down(K(a)*B*~K(a)) == 1/(a+1/b) ) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Versors Out of  $E_0$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Versors that are out of $E_0$ are made up of the versors within the original space. These include reflections and rotations, and their conformal representation is identical to their form in $G^n$, except the minus sign is dropped for reflections, "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Reflections"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$ -mam^{-1}  \\rightarrow MA\\tilde{M}  $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m = 5*e1 + 6*e2\n",
    "n = 7*e1 + 8*e2\n",
    "\n",
    "\n",
    "assert(down(m*up(a)*m) == -m*a*m.inv())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Rotations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$ mnanm = Ra\\tilde{R} \\rightarrow RA\\tilde{R}  $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "R = lambda theta: e**((-.5*theta)*(e12))\n",
    "theta = pi/2\n",
    "assert(down( R(theta)*up(a)*~R(theta)) == R(theta)*a*~R(theta))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Combinations of Operations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### simple example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As a simple example consider the combination  operations of translation,scaling, and inversion. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$b=-2a+e_0 \\quad \\rightarrow \\quad B= (T_{e_0}E_0 D_2) A \\tilde{ (D_2 E_0 T_{e_0})} $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "A = up(a)\n",
    "V = T(e1)*E0*D(2)\n",
    "B = V*A*~V\n",
    "assert(down(B) == (-2*a)+e1 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Transversion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A transversion may be built from a inversion, translation, and inversion. \n",
    "\n",
    "$$c = (a^{-1}+b)^{-1}$$\n",
    "\n",
    "In conformal GA, this is accomplished by \n",
    "\n",
    "$$C = VA\\tilde{V}$$\n",
    "\n",
    "$$V= e_+ T_b e_+$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "A = up(a)\n",
    "V = ep*T(b)*ep\n",
    "C = V*A*~V\n",
    "assert(down(C) ==1/(1/a +b))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Rotation about a point "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Rotation about a point $a$ can be achieved by translating the origin to $a$, then rotating, then translating back.  Just like the transversion can be thought of as translating the involution operator, rotation about a point can also be thought of as  translating the Rotor itself. Covariance.  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## More examples\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbsphinx-toctree": {
      "maxdepth": 1
    }
   },
   "source": [
    "[Visualization tools](visualization-tools.ipynb)\n",
    "\n",
    "[Object Oriented CGA](object-oriented.ipynb)\n",
    "\n",
    "[Interpolating Conformal Objects](interpolation.ipynb)\n",
    "\n",
    "[Clustering Geometric Objects](clustering.ipynb)",
    "\n",
    "[Robotic Manipulators](robotic-manipulators.ipynb)"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
